#include <iostream>
#include <cv.h>
#include <highgui.h>
#include <sstream>
#include <string>
#include <iomanip>

// Sample Functions
#include "BackgroundImageGenerator.h"
void backgroundGeneratorTest(const std::vector<cv::Mat>& trainingset, const cv::Mat& testImg);
#include "BackgroundSubtractor.h"
void backgroundSubtractorTest(const std::vector<cv::Mat>& trainingset, const cv::Mat& testImg);


int main(int argc, char **argv){
	// Test Sample
	cv::Mat img=cv::imread("test.jpg");

	// Loading Training Set
	std::vector<cv::Mat> trainingset;
	std::ostringstream oss;
	std::cerr << "Loading Training Set ... " << std::flush;
	for(int i=0;i<30;i++){
		oss.str("");
		oss << "data\\" << std::setw(4) << std::setfill('0') << i+1 << ".jpg";

		cv::Mat timg=cv::imread(oss.str());
		trainingset.push_back(timg);
	}
	std::cerr << "done" << std::endl;

	// sample functions
	backgroundGeneratorTest(trainingset, img);
	backgroundSubtractorTest(trainingset, img);

	return 0;
}


void backgroundGeneratorTest(const std::vector<cv::Mat>& trainingset, const cv::Mat& testImg){
	BackgroundImageGeneratorMedian bigMedian(10);
	BackgroundImageGeneratorMean bigMean(30);
	BackgroundImageGeneratorPCA bigPCA(3);
	BackgroundImageGeneratorIPCA bigIPCA(3);

	// Background Training
	std::cerr << "Training ... " << std::flush;
	bigMean.train(trainingset);
	bigMedian.train(trainingset);
	bigPCA.train(trainingset);
	bigIPCA.train(trainingset);
	std::cerr << "done" << std::endl;

	// Resulting Images
	cv::Mat result1,result2,result3,result4;

	// Generate and Show results
	cv::imshow("src", testImg);
	bigPCA.generate(testImg,result1);
	cv::imshow("TestPCA", result1);
	bigMean.generate(testImg,result2);
	cv::imshow("TestMean", result2);
	bigMedian.generate(testImg,result3);
	cv::imshow("TestMedian", result3);
	bigIPCA.generate(testImg,result4);
	cv::imshow("TestIPCA", result4);

	cv::waitKey();
}

void backgroundSubtractorTest(const std::vector<cv::Mat>& trainingset, const cv::Mat& testImg){
	BackgroundSubtractorParzenDensityEstimation<KernelFunctionEpanechnikov> bgsPDE;
	BackgroundSubtractorMedian bgsMedian(30,cv::Scalar(10,10,10));
	BackgroundSubtractorIPCA bgsIPCA(1,cv::Scalar(10,10,10));

	// Background Training
	std::cerr << "Training ... " << std::flush;
	bgsPDE.train(trainingset);
	bgsMedian.train(trainingset);
	bgsIPCA.train(trainingset);
	std::cerr << "done" << std::endl;

	// Resulting Images
	cv::Mat result1,result2,result3;

	// Subtraction and Show results
	bgsPDE.apply(testImg,result1);
	cv::imshow("bgsPDE", result1);
	bgsMedian.apply(testImg,result2);
	cv::imshow("bgsMedian", result2);
	bgsIPCA.apply(testImg,result3);
	cv::imshow("bgsIPCA", result3);
	cv::waitKey();
}

